Adopt monorepo structure#2565
Conversation
|
The performance metrics CI job fails because it uses the same setup command on |
|
@wojtekn, the dev build installs and runs fine on macOS for me. |
epeicher
left a comment
There was a problem hiding this comment.
Thanks @fredrikekelund for implementing these massive changes! I have tested different areas, and I have not found any issues. With regards to the scripts, I have tested:
| Platform | Test | Result |
|---|---|---|
| Mac | npm install |
✅ |
| Mac | npm start |
✅ |
| Mac | npm run make |
✅ |
| Windows | npm install |
✅ |
| Windows | npm start |
✅ |
I approve this as it works for me, but I'm open to feedback from others.
| @@ -1,6 +1,6 @@ | |||
| import fs from 'fs'; | |||
| import wpcomFactory from '@studio/common/lib/wpcom-factory'; | |||
| import { createMock } from 'src/lib/test-utils'; | |||
There was a problem hiding this comment.
Nit: The src alias maps to apps/studio/src, so this CLI test file imports from the Studio app. This breaks the isolation goal. createMock should be moved to tools/common or the test should use its own utility.
There was a problem hiding this comment.
Great catch 👍 This made me realize we should split the Vitest config the same way we do with the Vite config. This ensures the resolve aliases are identical between Vite and Vitest, and tests cannot import files that aren't accessible to source code files. I did this in 7ddeec8.
For a follow-up, we could consider improving this, an alternative to investigate is |
|
Also, I would like to note that when running |
|
@fredrikekelund I tried again, and it still crashes. I did the following:
When I launch Studio, it immediately crashes:
It doesn't seem as flakiness as it clearly misses library: I checked it more, and it is a symlink pointing to a build-time directory, which I guess, was removed after the build: Studio 1.7.4 installed from DMG has a symlink, too, but it seems to be relative, pointing to another dir from the package: |
That's super interesting! Thanks for highlighting, @epeicher. Worth considering. |
I'm taking another look and trying to reproduce this. The package/make routine varies between local environments and CI now (we package in isolation locally only). It's possible that this is causing the error you encountered, @wojtekn
Looking into this, too. Again, CI passed, but I'm running |
|
@epeicher, I couldn't reproduce the Windows error you described. @wojtekn, I could reproduce the error you described, and it was indeed related to the |

Related issues
Proposed Changes
Note
The grunt work in this PR was done using OpenAI Codex. 🚨 I know the size of the diff looks daunting, but aside from
package-lock.jsonchanges, this PR is mostly just moving files around, changing import paths and tweaking config files 🚨Note
As noted in #2565 (comment), it's expected that the performance tests are failing.
Warning
A consequence of this change is that
package-lock.jsonwill no longer govern the version of dependencies we ship in production releases. That's because we now have a single lockfile for all npm workspaces, but we use only the package-specificpackage.jsonfiles to install thenode_modulesdirectories shipped in production (without a lockfile). This is probably fine, but it means we should be a bit more conservative about the semver ranges we use inpackage.json. For example, we cannot use^3.0.46for@wp-playgrounddependencies if the intention is to ship3.0.46to production. For those cases, we should save the exact version inpackage.json.The CLI used to be more of an add-on to Studio, but as of v1.7.0, it's become integral to how Studio works. To reflect this, and to make the codebase easier to work with (for humans and AI agents), this PR adopts a proper monorepo structure.
So, what does "proper monorepo structure" mean here?
apps/cliand the Electron app code is moved toapps/studio. They now live side by side.apps/clicode and theapps/studiocode are now isolated – there are no cross imports../commonhad been made into a proper package, using@studio/commonas the package name. It now lives intools/common.@studio/common, so it's not consumed as a true npm module. This is because we'd need to add package exports for everything we want to consume outside that package (i.e., for basically every function/type/class). This seemed tedious to me, but if it's good practice for whatever reason, we can easily revisit it later.tools/, liketools/eslint-plugin-studio.npm installonce in the repo root, and you're good to go.package.jsonfiles and npm reconciles and dedupes everything into a singlenode_modulesdirectory and a singlepackage-lock.jsonfile.node_modulesdirectories that get copied into the packaged output. We handle this withinstall:bundlenpm scripts inapps/cli/package.jsonandapps/studio/package.json.apps/cli/node_modulesandapps/studio/node_modulesdirectories, which potentially messes up the npm workspace-powered dependency tree. So, if you runnpm run packagelocally, you would typically need to rerunnpm ciafter the script finishes to reconcile the dependency tree. It's easy for other developers to be stumped by this requirement, so I addressed it by adding ascripts/package-in-isolation.tsscript. The gist is that it copies the source files from the repo to a temporary directory, installs dependencies, runsinstall:bundleand the package/make script, and then copies the output back to the repo.Testing Instructions
CI should pass, and the dev build should install fine
Pre-merge Checklist